#include <process.h>
#include <crmatrix.h>
#include <crperform.h>
using namespace cr;

#include <discard/mathsdet.h>

void testperfomance()
{
	enum { level = 10, testcnt = 1 };
	//enum { level = 4, testcnt = 100000 };
	double arr[level][level];
	double a[level*level];
	for (int i=0; i<level; ++i) {
		for (int j=0; j<level; ++j) {
			double sig = (rand() & 0x1) ? 0.1 : 0.0;
			arr[i][j] = sig * rand();
			a[level*i+j] = arr[i][j];
		}
	}
	matrixmaths<double, level, level> mat(arr);
	double detval;
	bool ret;
	CPerformTest perform;
	perform.BeginTime();
	for (int n=0; n<testcnt; ++n)
	ret = mat.det(&detval);
	perform.EndTime();
	printf("time1:%d, det:%f, ret:%d\n", perform.TimeDelayMS(), detval, ret);
	perform.BeginTime();
	for (int n=0; n<testcnt; ++n)
	detval = det(a, level, &ret);
	perform.EndTime();
	printf("time2:%d, det:%f, ret:%d\n", perform.TimeDelayMS(), detval, !ret);
}

//don't define submatrix out of matrix class. 
//but now use the derived class from matrix only for test. 
class test_matrix : public matrixmaths<double, 4, 4>
{ public: static void test(); };


int _tmain(int argc, _TCHAR* argv[])
{
	test_matrix::test();
	testperfomance();
	system("PAUSE");
	return 0;
}

#define matrix_format4 \
	"\
|  %6.2f %6.2f %6.2f %6.2f  |\n\
|  %6.2f %6.2f %6.2f %6.2f  |\n\
|  %6.2f %6.2f %6.2f %6.2f  |\n\
|  %6.2f %6.2f %6.2f %6.2f  |\n\
"
#define matrix_format3 \
	"\
|  %6.2f %6.2f %6.2f  |\n\
|  %6.2f %6.2f %6.2f  |\n\
|  %6.2f %6.2f %6.2f  |\n\
"
#define matrix_format2 \
	"\
|  %6.2f %6.2f  |\n\
|  %6.2f %6.2f  |\n\
"
#define matrix_format1 \
	"\
|  %6.2f  |\n\
"

#define print4(mat) \
	printf(matrix_format4\
	, mat[0][0], mat[0][1], mat[0][2], mat[0][3]\
	, mat[1][0], mat[1][1], mat[1][2], mat[1][3]\
	, mat[2][0], mat[2][1], mat[2][2], mat[2][3]\
	, mat[3][0], mat[3][1], mat[3][2], mat[3][3])

#define print3(mat) \
	printf(matrix_format3\
	, mat[0][0], mat[0][1], mat[0][2]\
	, mat[1][0], mat[1][1], mat[1][2]\
	, mat[2][0], mat[2][1], mat[2][2])

#define print2(mat) \
	printf(matrix_format2\
	, sub2[0][0], sub2[0][1]\
	, sub2[1][0], sub2[1][1])

#define print1(mat) \
	printf(matrix_format1\
	, sub1[0][0])



void test_matrix::test()
{
	double arr[4][4] = {12,14,10,11,5,2,4,15,7,13,1,6,9,3,0,8};
	matrixmaths<double, 4, 4> mat0(arr);
	submatrixmaths<double, 4, 4> sub4(mat0);
	submatrixmaths<double, 4, 4> sub3(sub4, 1, 1);
	submatrixmaths<double, 4, 4> sub2(sub3, 1, 1);
	submatrixmaths<double, 4, 4> sub1(sub2, 1, 1);

	bool ret = false;
	double detval = 0;

	//////////////////////////////////////////////////////////////////////////
	printf("+++++++++++++++++ arr ++++++++++++++++\n");
	print4(arr);
	printf("++++++++++++++++++++++++++++++++++++++\n");
	//////////////////////////////////////////////////////////////////////////

	printf("\n");

	//////////////////////////////////////////////////////////////////////////
	printf("----------------- mat ----------------\n");
	print4(mat0);
	ret = mat0.det(&detval);
	printf("mat0.det( ): %6.2f \nret:%d\n", detval, ret);
	double am[] = {
		mat0[0][0], mat0[0][1], mat0[0][2], mat0[0][3],
		mat0[1][0], mat0[1][1], mat0[1][2], mat0[1][3],
		mat0[2][0], mat0[2][1], mat0[2][2], mat0[2][3],
		mat0[3][0], mat0[3][1], mat0[3][2], mat0[3][3]
	};
	detval = ::det(am, 4, &ret); ret = !ret;
	printf("::det(mat0): %6.2f \nret:%d\n", detval, ret);
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

	printf("\n");

	//////////////////////////////////////////////////////////////////////////
	printf("---------------- sub4 ----------------\n");
	print4(sub4);
	ret = sub4.det(&detval);
	printf("sub4.det( ): %6.2f \nret:%d\n", detval, ret);
	double a4[] = {
		sub4[0][0], sub4[0][1], sub4[0][2], sub4[0][3],
		sub4[1][0], sub4[1][1], sub4[1][2], sub4[1][3],
		sub4[2][0], sub4[2][1], sub4[2][2], sub4[2][3],
		sub4[3][0], sub4[3][1], sub4[3][2], sub4[3][3]
	};
	detval = ::det(a4, 4, &ret);ret = !ret;
	printf("::det(sub4): %6.2f \nret:%d\n", detval, ret);
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

	printf("\n");

	//////////////////////////////////////////////////////////////////////////
	printf("---------------- sub3 ----------------\n");
	print3(sub3);
	ret = sub3.det(&detval);
	printf("sub3.det( ): %6.2f \nret:%d\n", detval, ret);
	double a3[] = {
		sub3[0][0], sub3[0][1], sub3[0][2], 
		sub3[1][0], sub3[1][1], sub3[1][2],
		sub3[2][0], sub3[2][1], sub3[2][2]
	};
	detval = ::det(a3, 3, &ret);ret = !ret;
	printf("::det(sub3): %6.2f \nret:%d\n", detval, ret);
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

	printf("\n");

	//////////////////////////////////////////////////////////////////////////
	printf("---------------- sub2 ----------------\n");
	print2(sub2);
	ret = sub2.det(&detval);
	printf("sub2.det( ): %6.2f \nret:%d\n", detval, ret);
	double a2[] = {
		sub2[0][0], sub2[0][1],
		sub2[1][0], sub2[1][1]
	};
	detval = ::det(a2, 2, &ret);ret = !ret;
	printf("::det(sub2): %6.2f \nret:%d\n", detval, ret);
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

	printf("\n");

	//////////////////////////////////////////////////////////////////////////
	printf("---------------- sub1 ----------------\n");
	print1(sub1);
	ret = sub1.det(&detval);
	printf("sub1.det( ): %6.2f \nret:%d\n", detval, ret);
	double a1[] = {sub1[0][0]};
	detval = ::det(a1, 1, &ret);ret = !ret;
	printf("::det(sub1): %6.2f \nret:%d\n", detval, ret);
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

	printf("\n");

	//////////////////////////////////////////////////////////////////////////
	printf("----- type cast from submatrix to matrix -----\n");
	matrix4_f mat4(sub4);
	matrix3_f mat3(sub3);
	matrix2_f mat2(sub2);
	matrix<double, 1, 1> mat1(sub1);
	printf("\n");
	print4(mat4);
	printf("\n");
	print3(mat3);
	printf("\n");
	print2(mat2);
	printf("\n");
	print1(mat1);
	printf("\n");
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

	//////////////////////////////////////////////////////////////////////////
	printf("------------ test not rely -----------\n");
	printf("before mat2 changed. \n");
	printf("mat2[1][1] : %f\n", mat2[1][1]);
	printf("sub2[1][1] : %f\n", sub2[1][1]);
	mat2[1][1] = 1124;
	printf("\nafter mat2 changed. \n");
	printf("mat2[1][1] : %f\n", mat2[1][1]);
	printf("sub2[1][1] : %f\n", sub2[1][1]);
	printf("\nnot rely is right. \n");
	printf("--------------------------------------\n");
	//////////////////////////////////////////////////////////////////////////

}